package com.aliyun.messagemgt.util.redis;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created with IDEA
 *
 * @author:zhangxingxing 0027012120
 * @date:2019/1/25
 * @time:10:55
 */
public class Redis {

    private static Logger logger = LoggerFactory.getLogger(Redis.class);
    /**
     * SET IF NOT EXIST NX是不存在时才set
     */
    private static final String SET_IF_NOT_EXIST = "NX";
    /**
     * Only set the key if it already exist. XX是存在时才set
     */
    private static final String SET_ONLY = "XX";
    /**
     * 超时关键字  ， ， EX是秒，PX是毫秒
     */
    private static final String SET_WITH_EXPIRE_TIME = "EX";
    /**
     * 修改成功时返回值
     */
    private static final String LOCK_SUCCESS = "OK";

    private static final String DEFAULT_VALUE = "A";

    private static final String LUA_SCRIPT = "redis.call(\"HSET\", KEYS[1], KEYS[2], KEYS[3])\n" +
            "redis.call(\"expire\", KEYS[1], KEYS[4])\n";

    private static JedisPool JEDIS_POOL;

    public static void setup(String redisHost, String redisPassword, Integer redisPort, Integer timeout) {
        //创建jedis池配置实例
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(500);
        config.setMinIdle(50);
        config.setMaxWaitMillis(10000);
        config.setMaxTotal(2000);
        JEDIS_POOL = new JedisPool(config, redisHost, redisPort, timeout, redisPassword);
        logger.info("redis启动完成");
    }


    /**
     * 写入缓存(当不关是否存在不存在)
     *
     * @param key
     * @param value
     * @return
     */
    public static void setXX(final String key, String value, Integer expireTime) {
        if(StringUtils.isNotBlank(value)){
            Jedis jedis = JEDIS_POOL.getResource();
            jedis.set(key, value);
            jedis.expire(key, expireTime);
            jedis.close();
        }
    }

    public static void setXX(final String key, Object value) {
        Jedis jedis = JEDIS_POOL.getResource();
        try {
            jedis.set(key.getBytes(), serialize(value));
        } catch (Exception e) {
            logger.error("setXX:",e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }
    public static Object getXX(final String key) {
        Jedis jedis = JEDIS_POOL.getResource();
        Object getObject = null;
        try {
            byte[] getByte = jedis.get(key.getBytes());
            if (getByte==null){
                return null;
            }
            getObject = unserizlize(getByte);
        } catch (Exception e) {
            logger.error("getXX:",e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return getObject;
    }

    /**
     * 设定超时
     *
     * @param key
     * @param expireTime
     * @return
     */
    public static boolean setTimer(final String key, Integer expireTime) {
        Jedis jedis = JEDIS_POOL.getResource();
        String result = jedis.set(key, DEFAULT_VALUE, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
        jedis.close();
        return LOCK_SUCCESS.equals(result);
    }

    /**
     * 取值
     *
     * @param key
     * @return
     */
    public static String getValue(String key) {
        Jedis jedis = JEDIS_POOL.getResource();
        String value = jedis.get(key);
        jedis.close();
        return value;
    }

    /**
     * 获取jedis客户端
     *
     * @return
     */
    public static Jedis getJedis() {
        return JEDIS_POOL.getResource();
    }

   

    /**
     * 判断redis是否失效
     *
     * @return
     */
    public static Boolean exists(final String key) {
        Jedis jedis = JEDIS_POOL.getResource();
        Boolean result = jedis.exists(key);
        jedis.close();
        return result;
    }
    
    
   //=====================操作hash======================
    
    /**
     * hash set
     * @param key
     * @param field
     * @param value
     * @param expireTime
     */
    public static void hset(String key,String field, String value, Integer expireTime){
    	Jedis jedis = JEDIS_POOL.getResource();
        jedis.eval(LUA_SCRIPT, 4, key, field, value, String.valueOf(expireTime));
        jedis.close();
    }

    /**
     * 获取单个filed的值
     * @param key
     * @param field
     * @return
     */
    public static String hmget(String key,String field){
    	Jedis jedis = JEDIS_POOL.getResource();
    	jedis.close();
    	return jedis.hget(key, field);
    }
    
    /**
     * 获取多个filed域的值
     * @param key redis的key：模块名+业务名+日期+消息ID
     * @param depCodes 所有子部门的编码
     * @return
     */
    public static List<String> hmget(String key, List<String> depCodes){
    	Jedis jedis = JEDIS_POOL.getResource();

        // 从redis获取今天所有部门的值，然后筛选出符合要求的部分
        Map<String, String> allMsg = jedis.hgetAll(key);
    	List<String> countsList = new ArrayList<>();
    	for (String depCode : depCodes) {
    	    if (null != allMsg.get(depCode)) {
    	        countsList.add(allMsg.get(depCode));
            }
        }

    	jedis.close();
    	return countsList;
    }
    
   //=====================获取当天日期======================
    
    /**
     * 获取当前日期并且格式为yyyymmdd
     * @return
     */
    public static String generateDate(){
    	String date = LocalDate.now().toString().replaceAll("-", "");
    	return date;
    }

    private static byte[] serialize(Object object) {
        ObjectOutputStream objectOutputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(object);
            byte[] getByte = byteArrayOutputStream.toByteArray();
            return getByte;
        } catch (IOException e) {
            logger.error("serialize:",e);
        }
        return null;
    }

    private static Object unserizlize(byte[] binaryByte) {
        ObjectInputStream objectInputStream = null;
        ByteArrayInputStream byteArrayInputStream = null;
        byteArrayInputStream = new ByteArrayInputStream(binaryByte);
        try {
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            Object obj = objectInputStream.readObject();
            return obj;
        } catch (Exception e) {
            logger.error("unserialize:",e);
        }
        return null;
    }
}